package swg.shape;

import java.util.ArrayList;

import swg.utils.Utils;

public class Point implements IswgShape
{
	protected int x;
	protected int y;
	protected double rho;
	protected double phi;
	protected String style = "";
	protected int r = 3;
	static Point ZERO = new Point(0,0);

	public Point(int x, int y)
	{
		this.x = x;
		this.y = y;
		rho = Math.sqrt((x * 1.) * (x * 1.) + (y * 1.) * (y * 1.));
		phi = Utils.arcTg((y * 1.), (x * 1.));
	}

	public void setR(int r)
	{
		this.r = r;
	}

	public Point(double rho, double phi, Point c)
	{
		this.rho = rho;
		this.phi = phi;
		this.x =c.getX();
		this.y =c.getY();
	}

	public Point(double rho, double phi, int dx, int dy)
	{
		this.rho = rho;
		this.phi = phi;
		x = (int) (rho * Math.cos(phi)) + dx;
		y = (int) (rho * Math.sin(phi)) + dy;
	}

	public Point(double x3, double y3, String style2)
	{

		this.x = (int) x3;
		this.y = (int) y3;
		this.style = style2;
	}

	public Point(double x3, double y3)
	{

		this.x = (int) x3;
		this.y = (int) y3;
	}

	public String getStyle()
	{
		return style;
	}

	public void setStyle(String style)
	{
		this.style = style;
	}

	public int getX()
	{
		return x;
	}

	public void setX(int x)
	{
		this.x = x;
	}

	public int getY()
	{
		return y;
	}

	public void setY(int y)
	{
		this.y = y;
	}

	public double getRho()
	{
		return rho;
	}

	public void setRho(double rho)
	{
		this.rho = rho;
	}

	public double getPhi()
	{
		return phi;
	}

	public void setPhi(double phi)
	{
		this.phi = phi;
	}

	@Override
	public String toString()
	{
		return "Point [phi=" + Math.toDegrees(phi) + ", rho=" + rho + ", x=" + x + ", y=" + y + "]";
	}

	public Point Translate(int dx, int dy)
	{
		Point res = new Point(x + dx, y + dy);
		return res;
	}

	public Point getMiddlePoint(Point a)
	{
		double x1 = getX();
		double x2 = a.getX();
		double y1 = getY();
		double y2 = a.getY();
		double aaa = x2 - x1;
		double bbb = (y2 - y1);
		double x4 = x1 - bbb;
		double y4 = y2 + aaa - bbb;
		double x5 = x1 + aaa / 2;
		double y5 = y1 + bbb / 2;
		double x6 = x4 + aaa / 2;
		double y6 = y4 + bbb / 2;
		double ccc = x5 - x6;
		double ddd = y6 - y5;
		double xo = x6 + ccc / 2;
		double yo = y5 + ddd / 2;
		Point res = new Point(xo, yo);
		return res;
	}

	public Point getMiddlePointOnSegment(Point a)
	{
		double x1 = getX();
		double x2 = a.getX();
		double y1 = getY();
		double y2 = a.getY();
		double aaa = x2 - x1;
		double bbb = (y2 - y1);
		double x5 = x1 + aaa / 2;
		double y5 = y1 + bbb / 2;
		Point res = new Point(x5, y5);
		return res;
	}

	public Point[] getMiddlePointsOnSegment(Point a, int parts)
	{
		Point[] res = new Point[parts-1];
		double x1 = getX();
		double x2 = a.getX();
		double y1 = getY();
		double y2 = a.getY();
		double aaa = x2 - x1;
		double bbb = (y2 - y1);
		double x5 = aaa / parts;
		double y5 = bbb / parts;
		for (int i = 1; i < parts; i++)
		{
			res[i - 1] = new Point(x1 + x5 * i, y1 + y5 * i,"fill:grey");
		}
		return res;
	}

	@Override
	public int getR()
	{
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public String getSWGCode()
	{
		String swg = "<circle cx=\"" + x + "\" cy=\"" + y + "\" r=\"" + r + "\" " + (style.length() == 0 ? "" : "style=\"" + style + "\" ") + " />\n";
		return swg;
	}

	public String getCoordinates()
	{
		StringBuffer c = new StringBuffer(x+"");
		c.append(",");
		c.append(y);
		c.append( " ");
		return x + "," + y + " ";
	}

	public static ArrayList<Point> getHilbertCurve(Point p1, Point p2)
	{
		Branch basic = new Branch(p1, p2);
		double costant = Math.PI/2-basic.getPhi();
		Point[] c = p1.getMiddlePointsOnSegment(p2, 3);
		Branch branch = new Branch(c[0], c[1]);
		double side =branch.getR();
		Point p4= c[1].getNewPoint(side, costant);
		Point p5= p4.getNewPoint(side,0);
		Point p6 = p5.getNewPoint(side*2, costant);
		Point p7 = p6.getNewPoint(side, costant*2);
		Point p8 = p7.getNewPoint(side, costant*3);
		Point p9 = p8.getNewPoint(side, costant*2);
		Point p10 = p9.getNewPoint(side, costant);
		Point p11 = p10.getNewPoint(side, costant*2);
		Point p12 = p11.getNewPoint(side*2, costant*3);
		Point p13 = p12.getNewPoint(side, 0);
		Point p14 = p13.getNewPoint(side, costant*3 );

		ArrayList<Point> res = new ArrayList<Point>();
		res.add(p2);
		res.add(c[1]);
		res.add(p4);
		res.add(p5);
		res.add(p6);
		res.add(p7);
		res.add(p8);
		res.add(p9);
		res.add(p10);
		res.add(p11);
		res.add(p12);
		res.add(p13);
		res.add(p14);		
		res.add(p1);
		return res;
	}

	private Point getNewPoint(double rho, double phi)
	{
		int xx = this.getX();
		int yy = this.getY();
		Point p1 = new Point(rho,phi,xx,yy);
		return p1;
	}

	public ArrayList<Point> getKochCurve(Point p2)
	{

		double costant = Math.sqrt(3.) / 2;
		ArrayList<Point> res = new ArrayList<Point>();
		Point[] c = this.getMiddlePointsOnSegment(p2, 3);
		Branch branch = new Branch(c[0], c[1]);
		Point d = c[0].getMiddlePointOnSegment(c[1]);
		Point e = new Point(branch.getR() * costant, branch.getPhi() - Math.PI / 2, d.getX(), d.getY());
		e.setStyle("fill:blue");

		res.add(this);
		res.add(c[0]);
		res.add(e);
		res.add(c[1]);
		res.add(p2);

		return res;
	}



}
